<!--
 * @Author: Wushiqi
 * @Descripttion: 分段加载的表格
 * @Date: 2021-04-19 16:55:20
 * @LastEditor: Wushiqi
 * @LastEditTime: 2021-04-30 17:29:54
-->
<template>
  <div :style="{height: height}">
    <el-table
      ref="loadTable"
      v-loading="loading"
      :data="currentData"
      :border="border"
      :stripe="stripe"
      :height="showLoad ? 'calc(100% - 20px)' : '100%'"
      :highlight-current-row="highlightCurrentRow"
      class="load-table"
      @row-click="$emit('row-click', $event)"
    >
      <template v-for="(val, key) in columns">
        <el-table-column
          v-if="val.type"
          :key="key"
          :type="val.type"
          :label="val.label"
          :align="val.align ? val.align : textAlign"
          :min-width="val.minWidth"
          :width="val.width"
        />
        <el-table-column
          v-else
          :key="key"
          :prop="val.prop"
          :label="val.label"
          :align="val.align ? val.align : textAlign"
          :min-width="val.minWidth"
          :width="val.width"
          :show-overflow-tooltip="val.toolTip"
          :formatter="val.formatter"
        />
      </template>
    </el-table>
    <div v-if="showLoad" class="load-box"><i class="el-icon-loading" />&nbsp;&nbsp;加载中</div>
  </div>
</template>

<script>
/**
 * 使用方法
 * <load-table
 *  :loading="detailLoading"
 *  :data="detailTable"
 *  :columns="detailColumns"
 *  height="calc(100vh - 180px)"
 *  text-align="center"
 * />
 * 注意：
 * 1.为了确保分段加载有效，需要给父盒子添加最小宽度（min-width），限度是表头最多只能显示两行
 * 2.columns数据格式：
 * res = [
    { type: 'index', label: '序号', width: '60' },
    { prop: 'balanceTime', label: '结算日期', minWidth: '23%', toolTip: true, formatter: this.timeFormat },
    { prop: 'taskTypeName', label: '结算类型', minWidth: '15%' },
    { prop: 'balanceObject', label: '结算对象', width: this.flexColumnWidth('balanceObject', this.detailTable) }
  ]
 */
import { debounce } from '@/common/debounce'
import common from '@/common/common'
export default {
  props: {
    loading: {
      default: false,
      type: Boolean
    },
    data: {
      default: () => [],
      type: [Array, Object]
    },
    border: {
      default: true,
      type: Boolean
    },
    stripe: {
      default: true,
      type: Boolean
    },
    height: {
      default: '440px',
      type: [String, Number]
    },
    columns: {
      default: () => [],
      type: [Array, Object]
    },
    textAlign: {
      default: 'center',
      type: String
    },
    highlightCurrentRow: {
      default: false,
      type: Boolean
    }
  },
  data() {
    return {
      originData: [],
      currentData: [],
      needLoad: false,
      cutIndex: 0,
      showLoad: false
    }
  },
  watch: {
    data(val) {
      this.originData = common.deepCopy(val)
      if (this.originData.length >= 20) {
        this.needLoad = true
        this.currentData = this.originData.slice(0, 20)
        this.cutIndex = 20
      } else {
        this.needLoad = false
        this.currentData = this.originData
      }
    }
  },
  mounted() {
    this.$nextTick(() => {
      this.doLayout()
    })
    window.addEventListener('scroll', this.loadData, true)
    window.addEventListener('resize', this.doLayout)
  },
  beforeDestroy() {
    this.originData = []
    window.removeEventListener('scroll', this.loadData, true)
    window.removeEventListener('resize', this.doLayout)
  },
  beforeUpdate() {
    this.doLayout()
  },
  methods: {
    // 重新计算表格大小
    doLayout: debounce(function() {
      this.$nextTick(() => {
        this.$refs.loadTable.doLayout()
      })
    }, 500, false),
    setCurrentRow(row) {
      this.$refs.loadTable.setCurrentRow(row)
    },
    // 加载数据
    loadData: debounce(function() {
      if (this.needLoad) { // 需要分段加载才触发以下代码
        const offsetHeight = this.$refs.loadTable.$el.offsetHeight
        const scrollTop = this.$refs.loadTable.bodyWrapper.scrollTop // 一直都是0
        const scrollHeight = this.$refs.loadTable.bodyWrapper.scrollHeight
        let loadMore = offsetHeight + scrollTop + 50 >= scrollHeight
        if (loadMore) {
          loadMore = false
          this.showLoad = true
          const newData = this.originData.slice(this.cutIndex, this.cutIndex += 20)
          this.currentData.splice(this.cutIndex, 0, ...newData)
          this.$nextTick(() => {
            this.showLoad = false
          })
        }
      }
    }, 200, false)
  }
}
</script>

<style scoped lang="scss">
.load-box {
  width: 100%;
  text-align: center;
  line-height: 20px;
}
</style>
